package residue;

import parser.Constants;
import parser.IupacResidue;
import sugar.LinkageType;
import sugar.Stem;
import utils.TreeTools;

public class Link {

	/*Residue1 is near the root while Residue2 is near the leaves*/
	private int linNb;

	private AbstractResidue res1 = new AbstractResidue();
	private String res1Id = "";
	private int res1CtNumber;
	private String res1LinkageType = LinkageType.UnknownLinkageType.getSymbol().toString();//Constants.UNKNOWN;
	private String res1LinkagePosition = Constants.UNKNOWN_LINKAGE_POS;
	
	private AbstractResidue res2 = new AbstractResidue();
	private String res2Id = "";
	private int res2CtNumber;
	private String res2LinkageType = LinkageType.UnknownLinkageType.getSymbol().toString();//Constants.UNKNOWN;
	private String res2LinkagePosition = Constants.UNKNOWN_LINKAGE_POS;
	private String res2Anomer = Constants.UNKNOWN;
	
	
	
	public Link()
	{}
	
	public Link(String res1LinkagePosition, String res2LinkagePosition)
	{
		this.setRes1LinkagePosition(res1LinkagePosition);
		this.setRes2LinkagePosition(res2LinkagePosition);
	}
	
	public Link(String linkSeq, IupacResidue residue) throws Exception
	{
//		Link link = null;
		
		String anomer = Constants.UNKNOWN;
		String posres2 = LinkageType.UnknownLinkageType.getSymbol().toString();
		String posres1 = LinkageType.UnknownLinkageType.getSymbol().toString();//Constants.UNKNOWN_LINKAGE_POS;
		
		try
		{
			int dashPos = linkSeq.indexOf(Constants.DASH);
//			System.out.println("parseResidue parseLink dashPos: " + dashPos + ", ID: "+ this.id);
			
			if(dashPos!=linkSeq.length())
			{
				posres1=String.valueOf(linkSeq.charAt(dashPos+1));
//				System.out.println("parseResidue parseLink dashPos!=linkSeq.length()");
			}
		
			if(dashPos==1)//no anomer 
			{
				posres2=String.valueOf(linkSeq.charAt(dashPos-1));
//				System.out.println("parseResidue parseLink dashPos==1");
			}
			
			if(dashPos==2)//regular case for monosaccharide
			{
				anomer=String.valueOf(linkSeq.charAt(dashPos-2));
				posres2=String.valueOf(linkSeq.charAt(dashPos-1));
//				System.out.println("parseResidue parseLink dashPos==2");
			}

//			//Link has to be null if exception!!
//			link = new Link();	
			
			if(!residue.isTreeRoot())
			{
				this.setRes1(TreeTools.getPreviousResidue(residue).getAbstractResidue());
				this.setRes1Id(TreeTools.getPreviousResidue(residue).getId());
			}
			this.setRes2(residue.getAbstractResidue());
			this.setRes2Id(residue.getId());
			this.setRes2Anomer(anomer); // transfer to abstractResidue object!!
			this.setRes2LinkagePosition(posres2);
			this.setRes1LinkagePosition(posres1);
//			System.err.println("res1" + link.getRes1());
//			System.err.println("res2" + link.getRes2());
			this.setInferredLinkageTypes();
//			link.setInferredLinkagePositions();
			this.toString();
//			System.err.println("parseResidue parseLink link.toString()"+ link.toString());
			
		}
		catch(Exception ex)
		{
			if(linkSeq==null || linkSeq.length()==0)
			{
				System.err.println("Link Link(String linkSeq, IupacResidue residue) linkSeq is null for residue " + residue.getAbstractResidue().toString() + " with id " + residue.getId());				
			}
			else
			{
				System.err.println("Link Link(String linkSeq, IupacResidue residue) " + linkSeq + " / " + ex.getMessage());				
			}
		}
		
		try
		{
			residue.setAnomerToResidue(anomer);
		}
		catch(Exception ex)
		{
			System.err.println("IupacResidue createLink setAnomerToResidue error ");
		}

//		return link;
	}
	
	
	public int getLinNb() {
		return linNb;
	}

	public void setLinNb(int linNb) {
		this.linNb = linNb;
	}
	
	public String getRes1Id() {
		return res1Id;
	}
	public AbstractResidue getRes1() {
		return res1;
	}

	public void setRes1(AbstractResidue res1) {
		this.res1 = res1;
	}

	public void setRes1Id(String res1Id) {
		this.res1Id = res1Id;
	}
	public int getRes1CtNumber() {
		return res1CtNumber;
	}
	public void setRes1CtNumber(int res1CtNumber) {
		this.res1CtNumber = res1CtNumber;
	}
	public String getRes1LinkageType() {
		return res1LinkageType;
	}
	public void setRes1LinkageType(String res1LinkageType) {
		this.res1LinkageType = res1LinkageType;
	}
	public String getRes1LinkagePosition() {
		return res1LinkagePosition;
	}
	public void setRes1LinkagePosition(String res1LinkagePosition) {
		this.res1LinkagePosition = checkResLinkagePosition(res1LinkagePosition);
	}
	public String getRes2Id() {
		return res2Id;
	}
	public void setRes2Id(String res2Id) {
		this.res2Id = res2Id;
	}
	public AbstractResidue getRes2() {
		return res2;
	}

	public void setRes2(AbstractResidue res2) {
		this.res2 = res2;
	}
	public int getRes2CtNumber() {
		return res2CtNumber;
	}
	public void setRes2CtNumber(int res2CtNumber) {
		this.res2CtNumber = res2CtNumber;
	}
	public String getRes2LinkageType() {
		return res2LinkageType;
	}
	public void setRes2LinkageType(String res2LinkageType) {
		this.res2LinkageType = res2LinkageType;
	}
	public String getRes2LinkagePosition() {
		return res2LinkagePosition;
	}
	public void setRes2LinkagePosition(String res2LinkagePosition) {
		this.res2LinkagePosition = checkResLinkagePosition(res2LinkagePosition);
	}
	public String getRes2Anomer() {
		return res2Anomer;
	}

	public void setRes2Anomer(String res2Anomer) {
		this.res2Anomer = res2Anomer;
	}
	
	@Override
	public String toString() {
//		System.out.println("Link.toString() : " );
//		//System.out.println("	res1 : " + this.res1);
//		System.out.println("	res1Id : " + this.res1Id);
//		System.out.println("	res1CtNumber : " + this.res1CtNumber );
//		System.out.println("	res1LinkageType : " + this.res1LinkageType );
//		System.out.println("	res1LinkagePosition : " + this.res1LinkagePosition );
//		
//		//System.out.println("	res2 : " + this.res2);
//		System.out.println("	res2Id : " + this.res2Id);
//		System.out.println("	res2CtNumber : " + this.res2CtNumber );
//		System.out.println("	res2LinkageType : " + this.res2LinkageType );
//		System.out.println("	res2LinkagePosition : " + this.res2LinkagePosition );
//		System.out.println("	res2Anomer : " + this.res2Anomer);
		
		return super.toString();
	}
	
	//set before traversal algo
	public void setInferredLinkageTypes()
		{	
		if(res1!=null && res2!=null )
		{
		
		try
		{
			
		if(res1.isGenericMonosaccharideResidue())
		{
//			System.err.println(res2.getIupacResidue().toString());
			if(res2.isGenericMonosaccharideResidue())
			{
				res1LinkageType=LinkageType.o.getSymbol().toString(); //"o";
				res2LinkageType=LinkageType.d.getSymbol().toString(); //"d";
			}
			if(res2.isGenericSubstituentResidue())
			{
				
//				res1LinkageType="d";
				res2LinkageType=LinkageType.n.getSymbol().toString(); //"n";
				res2LinkagePosition="1";
				if(res2.isSulfateSubstituentResidue()){
					res1LinkageType=LinkageType.o.getSymbol().toString(); //"o";
				}
				else{
					res1LinkageType=LinkageType.d.getSymbol().toString(); //"d";
				}
			}
			
			if(res2.isGenericComposedResidue())
			{
				res1LinkageType=LinkageType.o.getSymbol().toString(); //"o";
				res2LinkageType=LinkageType.d.getSymbol().toString(); //"d";
			}
		}
		if(res1.isGenericSubstituentResidue())
		{
			if(res2.isGenericMonosaccharideResidue())
			{
				res1LinkageType=LinkageType.n.getSymbol().toString(); //"n";
				res1LinkagePosition="1";
				res2LinkageType=LinkageType.d.getSymbol().toString(); //"d";
			}
			//shoud not exist?
			if(res2.isGenericSubstituentResidue())
			{
				res1LinkageType=LinkageType.n.getSymbol().toString(); //"n";
				res1LinkagePosition="1";
				res2LinkageType=LinkageType.n.getSymbol().toString(); //"n";
				res2LinkagePosition="1";
			}
			if(res2.isGenericComposedResidue())
			{
				res1LinkageType=LinkageType.n.getSymbol().toString(); //"n";
				res1LinkagePosition="1";
				res2LinkageType=LinkageType.d.getSymbol().toString(); //"d";
			}
		}
		if(res1.isGenericComposedResidue())
		{
			if(res2.isGenericMonosaccharideResidue())
			{
				res1LinkageType=LinkageType.o.getSymbol().toString(); //"o";
				res2LinkageType=LinkageType.d.getSymbol().toString(); //"d";
			}
			if(res2.isGenericSubstituentResidue())
			{
				res2LinkageType=LinkageType.n.getSymbol().toString(); //"n";
				res2LinkagePosition="1";
				if(res2.isSulfateSubstituentResidue()){
					res1LinkageType=LinkageType.o.getSymbol().toString(); //"o";
				}
				else{
					res1LinkageType=LinkageType.d.getSymbol().toString(); //"d";
				}
				
//				res1LinkageType=LinkageType.d.getSymbol().toString(); //"d";
//				res2LinkageType=LinkageType.n.getSymbol().toString(); //"n";
//				res2LinkagePosition="1";
			}
			if(res2.isGenericComposedResidue())
			{
				res1LinkageType=LinkageType.o.getSymbol().toString(); //"o";
				res2LinkageType=LinkageType.d.getSymbol().toString(); //"d";
			}
		}
//		System.out.println("Link setLinkageTypes res1 : " + this.res1 + " " + this.res1Id);
//		System.out.println("Link setLinkageTypes res2 : " + this.res2 + " " + this.res2Id);
		}
		catch(Exception ex)
		{
			System.err.println("Link setLinkageTypes() : " + ex.getMessage());
			//throw ex;
		}
		}
		}
	
	
	//set before traversal algo
//		public void setInferredLinkagePositions()
//			{	
//			if(res1!=null && res2!=null )
//			{
//			String res1Name = this.res1.getClass().getSimpleName();
//			String res2Name = this.res2.getClass().getSimpleName();
//			
//			try
//			{
//				
//			if(res2Name.equals("NAc"))
//			{
//				if(res1Name.equals("Glc") || res1Name.equals("Gal"))
//				{
////					res1LinkagePosition="2";
////					res2LinkagePosition="1";
//				}
//				if(res1Name.equals("Kdn"))
//				{
////					res1LinkagePosition="5";
////					res2LinkagePosition="1";
//				}
//			}
//			
//			System.out.println("Link setLinkagePos res1 : " + this.res1 + " " + res1Name + " " + res1.getClass().getSuperclass().getSimpleName());
//			System.out.println("Link setLinkagePos res2 : " + this.res2 + " " + res2Name + " " + res2.getClass().getName());
//			}
//			catch(Exception ex)
//			{
//				System.err.println("Link setInferredLinkagePositions() : " + ex.getMessage());
//				//throw ex;
//			}
//		}
//	}
	
	public String checkResLinkagePosition(String pos) {
		String result=Constants.UNKNOWN_LINKAGE_POS;
		try
		{
			if(pos.length()==1 && Character.isDigit(pos.charAt(0)))
//			if(Character.isDigit(pos))
			result = String.valueOf(pos);
		}
		catch(Exception ex)
		{
			System.err.println(ex.getMessage());
		}
		return result;
	}
	
	public String getUndCTvalue()
	{
		String CTLink = getCTvalue();
		return "o"+ CTLink.substring(4,CTLink.length()-2) +"d" ;//CTLink.substring(CTLink.length()-1);
	}
	
	
	public String getCTvalue()
	{
		String result = "";
		
		//this.setInferredLinkageTypes();
		
		result = this.getLinNb()
					+ Constants.COLON 
					+ this.res1CtNumber//+ this.res1Id
					+ this.res1LinkageType
					+ Constants.openingParenthesis
					+ this.res1LinkagePosition
					+ Constants.LINKAGE_SEPARATOR
					+ this.res2LinkagePosition
					+ Constants.closingParenthesis
					+ this.res2CtNumber//+ this.res2Id
					+ this.res2LinkageType
					;
		
//		System.out.println("Link getCTvalue : " + result);			
					
		return result;
	}

}
